<?php
/**
 * @author Raven <karascanvas@qq.com>
 */

namespace library\tencent\wechat\admin_wechat;


use library\tencent\wechat\common\MessageHandler;
use think\Db;

class WechatMessageHandler extends MessageHandler
{
    private $cfg;


    public function __construct()
    {
        $this->cfg = config('WECHAT');
    }


    public static function instance()
    {
        return new WechatMessageHandler();
    }


    protected function defaultResponse(array $message)
    {
        return $this->createTextResponse($message, '请输入文字信息');
    }

    // <editor-fold defaultstate="collapsed" desc="上报地址事件">
    protected function onLocationEvent(array $message) {
        $Latitude = $message['Latitude'];//纬度
        $Longitude = $message['Longitude'];//经度
        $openid=$message['FromUserName'];
        //现在是每隔5秒自动返回的
        $data=array(
            'current_lat'=>$Latitude,
            'current_lng'=>$Longitude
        );
        $aid=Db::name('account_wechat')->where(['openid'=>$openid])->value('account_id');
        Db::name('account')->where(['id'=>$aid])->update($data);
        return 'success';
    }
    // </editor-fold>

// <editor-fold defaultstate="collapsed" desc="文本回复">
    protected function onTextMessage(array $req)
    {
        $rec = $this->getMatchedRecord($req['Content']);
        if (empty($rec)) {
            return $this->createTextResponse($req, '没有匹配的信息');
        }
        return $this->convertToResponse($req, $rec['type'], $rec['content']);
    }
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="关注回复">
    protected function onSubscribeEvent(array $req)
    {
        file_put_contents('./text4.txt','subscribe1',FILE_APPEND);
        $account_wechat=Db::name('account_wechat')->where(['openid'=>$req['FromUserName']])->find();
        file_put_contents('./text4.txt','subscribe2',FILE_APPEND);
        file_put_contents('./text4.txt',json_encode($account_wechat),FILE_APPEND);
        if($account_wechat and $account_wechat['subscribe'] != 1){
            Db::name('account_wechat')->where(['account_id'=>$account_wechat['account_id']])->setField('subscribe',1);
        }

        $item= Db::name('wechat_auto_reply')->where(['status' => 1,'is_welcome'=>1])->find();


        if($item['content']){
            return $this->convertToResponse($req, $item['type'], $item['content']);
//            return $this->createTextResponse($req, $item['content']);
        }else{
            return $this->createTextResponse($req, "欢迎您的到来");
        }
    }
// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="取消关注">
    protected function onUnSubscribeEvent(array $req) {
        file_put_contents('./text4.txt','unsubscribe1',FILE_APPEND);
        $account_wechat=Db::name('account_wechat')->where(['openid'=>$req['FromUserName']])->find();
//        file_put_contents('./text4.txt',$account_wechat,FILE_APPEND);
//        file_put_contents('./text4.txt','unsubscribe2',FILE_APPEND);
        if($account_wechat){
            Db::name('account_wechat')->where(['account_id'=>$account_wechat['account_id']])->setField('subscribe',0);
        }
    }
// </editor-fold>



    private function getMatchedRecord($content)
    {
        $key = 'wechat.auto_reply:' . md5($content);
        $rec = cache($key);
        if ($rec === false) {
            foreach ($this->getAllRecords() as $item) {
                if ($this->isMatch($item['match_type'], $item['pattern'], $content)) {
                    $rec = $item;
                    break;
                }
            }
            if (!$rec) {
                $rec = array();
            }
            cache($key, $rec, 5);
        }
        return $rec;
    }


    private static $matchers = [
        0 => 'isKeywordMatch',
        1 => 'isWildcardMatch',
        2 => 'isRegexMatch',
        9 => 'isCustomMatch',
    ];


    private function isMatch($type, $pattern, $content)
    {
        if (strlen($pattern) == 0 || strlen($content) == 0) {
            return false;
        }
        if (isset(static::$matchers[$type])) {
            $func = static::$matchers[$type];
            if (is_string($func) && method_exists($this, $func)) {
                return call_user_func(array($this, $func), $pattern, $content);
            } else if (is_callable($func)) {
                return call_user_func($func, $pattern, $content);
            }
        }
        return false;
    }


    protected function isKeywordMatch($pattern, $content)
    {
        $keywords = explode('|', $pattern);
        foreach ($keywords as $keyword) {
            if (strpos($content, $keyword) > -1) {
                return true;
            }
        }
        return false;
    }


    protected function isWildcardMatch($pattern, $content)
    {
        // todo impl wildcard match
        return false;
    }


    protected function isRegexMatch($pattern, $content)
    {
        return preg_match($pattern, $content);
    }


    protected function isCustomMatch($pattern, $content)
    {
        if (is_callable($pattern)) {
            return call_user_func($pattern, $content);
        }
        return false;
    }


    private function getAllRecords()
    {
        $key = 'table:wechat_auto_reply';
//        if (APP_DEBUG) {
//            cache($key,null);
//        }
        $data = cache($key);
        if ($data === false) {
            $temp = Db::name('wechat_auto_reply')->where(['status' => 1])->order('priority desc')->select();
            $data = array();
            foreach ($temp as $item) {
                if (in_array($item['type'], [3, 4, 5])) {
                    $item['content'] = json_decode($item['content'], true);
                }
                $data[] = $item;
            }
            cache($key, $data);
        }
        return $data;
    }


    private function convertToResponse($req, $type, $content)
    {
        switch ($type) {
            case 0 :
                return $this->createTextResponse($req, $content);
            case 1:
                return $this->createImageResponse($req, $content);
            case 2:
                return $this->createVoiceResponse($req, $content);
            case 3:
                return $this->createVideoResponse($req, $content['MediaId'], $content['Title'], $content['Description']);
            case 4:
                return $this->createMusicResponse($req, $content['Title'], $content['Description'], $content['MusicURL'], $content['HQMusicUrl'], $content['ThumbMediaId']);
            case 5:
                return $this->createNewsResponse($req, $content);
        }
        return null;
    }

}